import { ref } from 'vue';
import { useCurrentWatchStore } from '@T2/store/users.ts';
import { isJSON } from '@T2/utils/utils.ts';
import { sensorApi, sensorByIdDiff, unitApi, unitById } from "@T2/service/api.ts";

export const getMenuParams = (menu_path: string) => {
  const currentWatchStore = useCurrentWatchStore();
  
  const findMenuByPath = (tree: any[], menu_path: string): any | null => {
    for (const node of tree) {
      if (node.menu__path === menu_path) {
        return node; // 找到匹配的节点，直接返回
      }
      if (node.children && node.children.length > 0) {
        const result = findMenuByPath(node.children, menu_path);
        if (result) {
          return result; // 如果在子节点中找到匹配的节点，返回结果
        }
      }
    }
    return null; // 没找到返回 null
  }
  const menu = findMenuByPath(currentWatchStore.curMenus, menu_path);
  if (!menu || !isJSON(menu.params)) {
    return {};
  }
  const { sensors, pictures, zts, flows, special } = JSON.parse(menu.params);
  return { sensors, pictures, zts, flows, special };
}

interface SensorsNode {
  c?: SensorsNode[];
  n?: string;
  t: 'v' | 'vd' | 'vm' | 'vy' | 'c' | 'ch' | 'cd' | 'cm' | 'cy';
  s?: number | null;
  unit?: string;
  timestamp?: string;
  value?: string;
}
export const getLastdata = async (sensors: SensorsNode[]): Promise<{ curIds: SensorsNode[]; diffIds: SensorsNode[]; }> => {
  let curIds: SensorsNode[] = [];
  let diffIds: SensorsNode[] = [];
  
  const collectIds = (item: SensorsNode) => {
    if (item.c) {
      item.c.forEach(i => collectIds(i));
    } else {
      if (item.t === 'v') {
        curIds.push(item);			//引用sensors对应变量
      } else if (['vd', 'vm', 'vy'].includes(item.t)) {
        diffIds.push(item);     //引用sensors对应变量
      }
    }
  }
  sensors.forEach(i => {
    collectIds(i);
  });
  
  if (curIds.length > 0) {
    const ids = curIds.map(i => i.s).filter((id): id is number => id !== null);
    if (ids.length) {
      const res: any = await sensorApi({
        method: "get",
        params: {
          page: 1,
          id__in: ids.toString(),
        },
      });
      let { results } = res;
      curIds.forEach(i => {
        let item = results.find((v: any) => v.id === i.s);
        if (item) {
          i.unit = item.unit;
          i.timestamp = item.timestamp;
          i.value = item.lastdata_cn;
        }
      });
    }
  }
  
  const getSensorByIdDiff = (id: number) => {
    return new Promise((resolve, reject) => {
      sensorByIdDiff({
        method: 'get',
        id: id,
        params: {}
      }).then((res: any) => {
        resolve(res);
      }).catch((res: any) => {
        reject(res);
      });
    })
  }
  if (diffIds.length > 0) {
    const uniqueIds = Array.from(new Set(diffIds.map(i => i.s).filter((id): id is number => id !== null)));
    const res: any = await Promise.all(uniqueIds.map(id => getSensorByIdDiff(id)));
    res?.forEach((item: any, index: number) => {
      const id = uniqueIds[index];
      diffIds.forEach(i => {
        if (i.s === id) {
          i.unit = item.unit;
          if (i.t === 'vd') {
            i.value = item.today;
          } else if (i.t === 'vm') {
            i.value = item.month;
          } else if (i.t === 'vy') {
            i.value = item.year;
          }
        }
      });
    });
  }
  return { curIds, diffIds };
}

interface UnitResults {
  id: number;
  name: string;
  params: string;
  _sensors?: SensorsNode[];
}

/**
 * 获取站点列表，处理站点中的params。
 * 
 * @param menu_path - 过滤每个站点 `params.sensors` 数组中符合条件的对象，默认从后台配置成菜单的实际路径。
 * 
 * @returns 一个对象，包含以下属性：
 *   - `unitList` - 经过过滤和处理后的站点列表，其中会新增一个属性_sensors。
 *   - `curIds` - `params._sensors` 中所有变量对象的引用组成的数组。
 */
export const getUnitsParams = async (menu_path: string) => {
  const getUnitList = () => {
    return new Promise((resolve, reject) => {
      unitApi({
        method: 'get',
        params: {
          ordering: 'code',
        }
      }).then((res: any) => {
        resolve(res);
      }).catch((res: any) => {
        reject(res);
      });
    });
  }

  const solveUnit = async (results: UnitResults[]) => {
    const unitList = results.filter((i: any) => {
      if (!isJSON(i.params)) {
        return false;
      }
      const { sensors }: { sensors: SensorsNode[] } = JSON.parse(i.params);
      const currentMenuSensors = sensors?.find(i => i.n === menu_path)?.c || [];
      if (!currentMenuSensors?.length) {
        return false;
      }
      i._sensors = currentMenuSensors;
      return true;
    }) || [];

    const datas = unitList.map(i => {
      return { c: i._sensors } as SensorsNode;
    });
    const { curIds }: { curIds: SensorsNode[] } = await getLastdata(datas);

    return { unitList, curIds };
  }

  const res: any = await getUnitList();
  const results = ref(res.results as UnitResults[]);
  
  return solveUnit(results.value);
}

/**
 * 获取站点列表，处理站点中的params。
 * 
 * @param menu_path - 过滤每个站点 `params.sensors` 数组中符合条件的对象，默认从后台配置成菜单的实际路径。
 * @param unitID - 如果为传入该参数，则直接获取该站点详情，否则获取站点列表取第一个站点。
 * 
 * @returns 一个对象，包含以下属性：
 *   - `unit` - 站点详情，其中会新增一个属性_sensors，若该站点未配置参数，则unit为null，。
 *   - `curIds` - `params._sensors` 中所有变量对象的引用组成的数组。
 */
export const getUnitParams = async (menu_path: string, unitID: number | undefined) => {
  const getUnitList = () => {
    return new Promise((resolve, reject) => {
      unitApi({
        method: 'get',
        params: {
          ordering: 'code',
          pagesize: 1,
        }
      }).then((res: any) => {
        resolve(res?.results?.length ? res?.results[0] : null);
      }).catch((res: any) => {
        reject(res);
      });
    });
  }
  
  const getUnitDetail = (id: number) => {
    return new Promise((resolve, reject) => {
      unitById({
        method: 'get',
        id,
      }).then((res: any) => {
        resolve(res);
      }).catch((res: any) => {
        reject(res);
      });
    });
  }

  const solveUnit = async (results: UnitResults | null) => {
    let curIds: SensorsNode[] = [];
    
    if (!results || !isJSON(results.params)) {
      return { unit: null, curIds: [] };
    }
    const { sensors }: { sensors: SensorsNode[] } = JSON.parse(results.params);
    const currentMenuSensors = sensors?.find(i => i.n === menu_path)?.c || [];
    if (!currentMenuSensors?.length) {
      return { unit: null, curIds };
    }
    results._sensors = currentMenuSensors;
    const { curIds: arr0 } = await getLastdata(results._sensors);
    curIds = arr0;

    return { unit: results, curIds };
  }
  
  const res: any = await (unitID ? getUnitDetail(unitID) : getUnitList());
  const results = ref(res as UnitResults | null);
  
  return solveUnit(results.value);
}